package com.yh.service.redis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yh.config.OtherSource;
import com.yh.dao.UserDao;
import com.yh.entity.User;
import com.yh.utils.Constants;
import com.yh.utils.ImgUrl;
import com.yh.vo.MovieVO;
import io.minio.MinioClient;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.text.DecimalFormat;
import java.util.concurrent.TimeUnit;

/**
 * 更新缓存
 *
 * @author yuhuan
 * @date 2022/01/13
 */
@DubboService
public class UpdateDataToRedisImpl implements UpdateDataToRedis {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MinioClient minioClient;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private UserDao userDao;
    @Autowired
    private OtherSource otherSource;

    /**
     * 同步登录用户的信息
     */
    @Override
    public void updateLoginUser(String userId) {
        User user = userDao.findUserById(userId);
        // 处理用户的头像信息
        user = ImgUrl.userImageHandler(minioClient, otherSource, user);
        saveUserToRedis(user);
    }

    /**
     * 清理登录用户的信息
     */
    @Override
    public void clearLoginUser(String userId) {
        // 清除redis中的用户登录信息
        redisTemplate.delete(createUserIdInRedis(userId));
    }

    /**
     * 将用户信息保存到缓存并设置有效时间
     */
    @Override
    public void saveUserToRedis(User user) {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // 处理用户头像
        user = ImgUrl.userImageHandler(minioClient, otherSource, user);
        try {
            String userJson = objectMapper.writeValueAsString(user);
            String userIdInRedis = createUserIdInRedis(user.getUserId());
            valueOperations.set(userIdInRedis, userJson, Constants.LoginData.LOGIN_EXPIRE_TIME, TimeUnit.MINUTES);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将电影信息保存到redis
     */
    @Override
    public void saveMovieDetailToRedis(MovieVO movieVO) {
        // 获取字符串类型的操作模板
        ValueOperations operations = redisTemplate.opsForValue();
        try {
            // 将数据模型序列化
            String movieVoJson = objectMapper.writeValueAsString(movieVO);
            // 计算过期时间（固定值+随机值）
            Double randomTime = 30 * 60 + Math.random() * 10;
            // 去除小数部分
            DecimalFormat decimalFormat = new DecimalFormat("0");
            Long expireTime = Long.valueOf(decimalFormat.format(randomTime));
            // 创建该影片数据在缓存中存在的唯一ID
            String movieId = createMovieIdInRedis(movieVO.getMovie().getMovieId());
            // 将电影的数据模型信息缓存到redis并设置缓存的过期时间
            operations.set(movieId, movieVoJson, expireTime, TimeUnit.SECONDS);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 清理旧的影片信息
     */
    @Override
    public boolean clearMovie(int movieId) {
        // 创建影片数据在缓存中存在的唯一ID
        String movieIdInRedis = createMovieIdInRedis(movieId);
        Boolean hasKey = redisTemplate.hasKey(movieIdInRedis);
        if (hasKey) {
            return redisTemplate.delete(movieIdInRedis);
        }
        return !hasKey;
    }

    /**
     * 拼接目标影片在缓存中的唯一ID
     */
    @Override
    public String createMovieIdInRedis(int movieId) {
        String movieIdInRedis = "movie:movieVO:" + String.valueOf(movieId);
        return movieIdInRedis;
    }

    /**
     * 生成用户在缓存中的KEY
     */
    @Override
    public String createUserIdInRedis(String userId) {
        return Constants.LoginData.LOGIN_DATA_PREFIX_KEY + ":" + userId;
    }
}
